import Cocoa
import FlutterMacOS
import AVKit

@main
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    return true
  }

  override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
    return true
  }
  
  override func applicationDidFinishLaunching(_ notification: Notification) {
    let controller = mainFlutterWindow?.contentViewController as! FlutterViewController
    DirectoryAccessPlugin.register(with: controller.registrar(forPlugin: "DirectoryAccessPlugin"))
    NativeVideoPlayerPlugin.register(with: controller.registrar(forPlugin: "NativeVideoPlayerPlugin"))
  }
}

// 目录访问插件
public class DirectoryAccessPlugin: NSObject, FlutterPlugin {
    private var accessedURLs: [String: URL] = [:]
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "directory_access", binaryMessenger: registrar.messenger)
        let instance = DirectoryAccessPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "selectDirectory":
            selectDirectory(result: result)
        case "hasDirectoryAccess":
            hasDirectoryAccess(call: call, result: result)
        case "startAccessingDirectory":
            startAccessingDirectory(call: call, result: result)
        case "stopAccessingDirectory":
            stopAccessingDirectory(call: call, result: result)
        case "saveDirectoryBookmark":
            saveDirectoryBookmark(call: call, result: result)
        case "restoreDirectoryBookmark":
            restoreDirectoryBookmark(call: call, result: result)
        default:
            result(FlutterMethodNotImplemented)
        }
    }
    
    private func selectDirectory(result: @escaping FlutterResult) {
        let openPanel = NSOpenPanel()
        openPanel.canChooseFiles = false
        openPanel.canChooseDirectories = true
        openPanel.allowsMultipleSelection = false
        openPanel.canCreateDirectories = false
        
        let response = openPanel.runModal()
        if response == .OK {
            guard let url = openPanel.url else {
                result(nil)
                return
            }
            
            // 获取安全作用域访问权限
            _ = url.startAccessingSecurityScopedResource()
            accessedURLs[url.path] = url
            
            // 保存书签
            do {
                let bookmark = try url.bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
                UserDefaults.standard.set(bookmark, forKey: "directory_bookmark_\(url.path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "")")
            } catch {
                print("保存目录书签失败: \(error)")
            }
            
            result(url.path)
        } else {
            result(nil)
        }
    }
    
    private func hasDirectoryAccess(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let path = args["path"] as? String else {
            result(false)
            return
        }
        
        let accessible = FileManager.default.isReadableFile(atPath: path)
        result(accessible)
    }
    
    private func startAccessingDirectory(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let path = args["path"] as? String else {
            result(false)
            return
        }
        
        // 尝试从书签恢复访问权限
        if restoreFromBookmark(path: path) {
            result(true)
            return
        }
        
        let url = URL(fileURLWithPath: path)
        let success = url.startAccessingSecurityScopedResource()
        if success {
            accessedURLs[path] = url
        }
        result(success)
    }
    
    private func stopAccessingDirectory(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let path = args["path"] as? String else {
            result(nil)
            return
        }
        
        if let url = accessedURLs[path] {
            url.stopAccessingSecurityScopedResource()
            accessedURLs.removeValue(forKey: path)
        }
        result(nil)
    }
    
    private func saveDirectoryBookmark(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let path = args["path"] as? String else {
            result(false)
            return
        }
        
        let url = URL(fileURLWithPath: path)
        do {
            let bookmark = try url.bookmarkData(options: [.withSecurityScope], includingResourceValuesForKeys: nil, relativeTo: nil)
            let key = "directory_bookmark_\(path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "")"
            UserDefaults.standard.set(bookmark, forKey: key)
            result(true)
        } catch {
            print("保存目录书签失败: \(error)")
            result(false)
        }
    }
    
    private func restoreDirectoryBookmark(call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let path = args["path"] as? String else {
            result(false)
            return
        }
        
        let success = restoreFromBookmark(path: path)
        result(success)
    }
    
    private func restoreFromBookmark(path: String) -> Bool {
        let key = "directory_bookmark_\(path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "")"
        guard let bookmark = UserDefaults.standard.data(forKey: key) else {
            return false
        }
        
        do {
            var isStale = false
            let url = try URL(resolvingBookmarkData: bookmark, options: [.withSecurityScope], relativeTo: nil, bookmarkDataIsStale: &isStale)
            
            if isStale {
                print("书签已过期，需要重新选择目录")
                return false
            }
            
            let success = url.startAccessingSecurityScopedResource()
            if success {
                accessedURLs[path] = url
            }
            return success
        } catch {
            print("恢复目录书签失败: \(error)")
            return false
        }
    }
}

// 原生视频播放器插件

public class NativeVideoPlayerPlugin: NSObject, FlutterPlugin {
    
    public static func register(with registrar: FlutterPluginRegistrar) {
        let factory = VideoPlayerViewFactory(messenger: registrar.messenger)
        registrar.register(factory, withId: "native_video_player_view")
    }
}

// Platform View Factory
class VideoPlayerViewFactory: NSObject, FlutterPlatformViewFactory {
    private weak var messenger: FlutterBinaryMessenger?

    init(messenger: FlutterBinaryMessenger) {
        self.messenger = messenger
        super.init()
    }

    func create(withViewIdentifier viewId: Int64, arguments args: Any?) -> NSView {
        let frame = NSRect(x: 0, y: 0, width: 300, height: 200)
        let platformView = VideoPlayerPlatformView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger)
        return platformView.view()
    }
}

// Platform View Implementation
class VideoPlayerPlatformView: NSObject {
    private var _view: NSView
    private var playerLayer: AVPlayerLayer
    private var player: AVPlayer?
    private var methodChannel: FlutterMethodChannel

    init(frame: NSRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
        _view = NSView()
        playerLayer = AVPlayerLayer()
        
        let channelName = "native_video_player_\(viewId)"
        methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: messenger!)
        
        super.init()
        
        setupView(frame: frame)
        setupMethodChannel()
        
        // 如果有初始参数（视频路径），立即加载
        if let arguments = args as? [String: Any], let videoPath = arguments["videoPath"] as? String {
            loadVideo(path: videoPath)
        }
    }
    
    private func setupView(frame: NSRect) {
        _view.frame = frame
        _view.wantsLayer = true
        _view.layer?.backgroundColor = NSColor.black.cgColor
        
        // 设置播放器层
        playerLayer.frame = _view.bounds
        playerLayer.videoGravity = .resizeAspect
        playerLayer.backgroundColor = NSColor.black.cgColor
        
        _view.layer?.addSublayer(playerLayer)
        
        print("设置视图: frame=\(frame), playerLayer.frame=\(playerLayer.frame)")
    }
    
    private func setupMethodChannel() {
        methodChannel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
            switch call.method {
            case "loadVideo":
                if let args = call.arguments as? [String: Any], let path = args["path"] as? String {
                    self?.loadVideo(path: path)
                    result(nil)
                } else {
                    result(FlutterError(code: "INVALID_ARGUMENTS", message: "视频路径无效", details: nil))
                }
            case "play":
                self?.player?.play()
                result(nil)
            case "pause":
                self?.player?.pause()
                result(nil)
            case "stop":
                self?.player?.pause()
                self?.player?.seek(to: .zero)
                result(nil)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    
    private func loadVideo(path: String) {
        let videoURL: URL
        
        // 判断是本地文件还是HTTP URL
        if path.hasPrefix("http://") || path.hasPrefix("https://") {
            guard let url = URL(string: path) else {
                print("无效的URL: \(path)")
                return
            }
            videoURL = url
            print("使用HTTP URL加载视频: \(path)")
        } else {
            // 检查本地文件是否存在
            guard FileManager.default.fileExists(atPath: path) else {
                print("视频文件不存在: \(path)")
                return
            }
            videoURL = URL(fileURLWithPath: path)
            print("使用本地文件加载视频: \(path)")
        }
        
        print("加载视频: \(path)")
        
        // 清理之前的播放器
        player?.pause()
        player = nil
        
        // 创建新的播放器
        player = AVPlayer(url: videoURL)
        playerLayer.player = player
        
        // 监听播放器状态
        NotificationCenter.default.addObserver(
            forName: .AVPlayerItemDidPlayToEndTime,
            object: player?.currentItem,
            queue: .main
        ) { _ in
            print("视频播放结束")
        }
        
        // 等待视频就绪后播放
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print("开始播放视频")
            self.player?.play()
            
            // 检查播放状态
            DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                if let player = self.player {
                    print("播放器状态: rate=\(player.rate), error=\(String(describing: player.error))")
                    if let item = player.currentItem {
                        print("播放项状态: \(item.status.rawValue), error=\(String(describing: item.error))")
                    }
                }
            }
        }
    }

    func view() -> NSView {
        return _view
    }
}
